package com.joinway.framework.core.aspect;

import java.lang.reflect.Method;
import java.sql.Connection;

import javax.sql.DataSource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceUtils;

import com.joinway.framework.core.utils.AopHelper;
import com.joinway.framework.data.jdbc.repository.MultiDataSourceTableRepository;
import com.joinway.framework.data.jdbc.repository.TableRepository;

@Aspect
class TableRepositoryTransactionalAspect {
	private final static Logger log = LoggerFactory.getLogger(TableRepositoryTransactionalAspect.class);
	
//	@Autowired DataSource dataSource;
	
	public Object doAround(ProceedingJoinPoint point) throws Throwable {
		Method method = AopHelper.getMethod(point);
//		log.debug("invoke method -> " + method)
		TableRepository target = (TableRepository)point.getTarget();
		
		Object value = null;
		
		DataSource dataSource = null;
		Connection conn = null;
		
		Throwable tt = null;
		long start = 0;
		
		try{
			dataSource = target.getSqlClient().getDataSource();
			conn = DataSourceUtils.getConnection(dataSource);
			TableRepository repository;
			
			if(target instanceof MultiDataSourceTableRepository){
				MultiDataSourceTableRepository mrepo = new MultiDataSourceTableRepository(conn);
				Integer index = ((MultiDataSourceTableRepository)target).getReadOnlyDataSourceIndex();
				if(index != null){
					mrepo.useReadOnlyDataSource(index);
				}
				repository = mrepo;
			}else{
				repository = new TableRepository(conn);
			}
			
			start = System.currentTimeMillis();
			value = method.invoke(repository, point.getArgs());
		}catch(Throwable t){
			tt = t;
			throw t;
		}finally{
			if(tt == null){
				long end = System.currentTimeMillis();
				log.info("sql cost {} ms", (end - start));
			}
			
			if(conn != null && dataSource != null){
				DataSourceUtils.releaseConnection(conn, dataSource);
			}
		}
		
		return value;
	}
}
